package cn.wolfcode.service.impl;

import cn.wolfcode.common.web.Result;
import cn.wolfcode.domain.Product;
import cn.wolfcode.domain.SeckillProduct;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.feign.ProductFeignApi;
import cn.wolfcode.mapper.SeckillProductMapper;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.ISeckillProductService;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


@Service
@Transactional
public class SeckillProductServiceImpl implements ISeckillProductService {
    @Autowired
    private SeckillProductMapper seckillProductMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private ProductFeignApi productFeignApi;

    @Override
    public List<SeckillProductVo> listByType(int type) {
        // 参数校验
        if (StringUtils.isEmpty(type + "")) {
            return null;
        }
        // 查询秒杀商品信息
        List<SeckillProduct> seckillProducts = seckillProductMapper.queryCurrentlySeckillProduct(type);
        // 获取秒杀商品对应的商品的id集合
        List<Long> ids = seckillProducts.stream().map(SeckillProduct::getProductId).collect(Collectors.toList());
        // 查询商品信息
        Result<List<Product>> productResult = productFeignApi.listByIds(ids);
        // 封装成vo对象
        if (!productResult.hasError()) {
            HashMap<Long, Product> productMap = new HashMap<>();
            productResult.getData().forEach(p->productMap.put(p.getId(),p));
            ArrayList<SeckillProductVo> vos = new ArrayList<>();
            for (SeckillProduct seckillProduct : seckillProducts) {
                SeckillProductVo vo = new SeckillProductVo();
                Product product = productMap.get(seckillProduct.getProductId());
                BeanUtils.copyProperties(product, vo);
                BeanUtils.copyProperties(seckillProduct, vo);
                vos.add(vo);
            }
            return vos;
        }
        return null;
    }

    @Override
    public List<SeckillProductVo> queryByTime(int time) {
        if (StringUtils.isEmpty(time + "")) {
            return null;
        }
        List<Object> list = redisTemplate.opsForHash().values(SeckillRedisKey.SECKILL_PRODUCT_LIST.getRealKey(time + ""));
        if (list.size() > 0) {
            List<SeckillProductVo> vos = new ArrayList<>();
            list.forEach(vo->vos.add(JSON.parseObject((String) vo, SeckillProductVo.class)));
            return vos;
        }
        return Collections.emptyList();
    }

    @Override
    public SeckillProductVo find(int type, Long seckillId) {
        if (StringUtils.isEmpty(type + "") || seckillId == null) {
            return null;
        }
        String seckillProduct = (String) redisTemplate.opsForHash().get(SeckillRedisKey.SECKILL_PRODUCT_LIST.getRealKey(type + ""), seckillId.toString());
        return JSON.parseObject(seckillProduct, SeckillProductVo.class);
    }

    @Override
    public void decrStockCount(Long seckillId) {
        seckillProductMapper.decrStock(seckillId);
    }

    @Override
    public void rollbackRedisStock(Integer time, Long seckillId) {
        if (time != null && seckillId != null) {
            // 查询mysql中的库存
            int stockCount = seckillProductMapper.getStockCount(seckillId);
            // 设置到redis中
            redisTemplate.opsForHash().put(SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(time + ""), seckillId + "", stockCount + "");
        }
    }

    @Override
    public void incrStock(Long seckillId) {
        if (seckillId != null) {
            seckillProductMapper.incrStock(seckillId);
        }
    }
}
